package com.example.management.system.service.impl


import com.example.management.common.config.BootdoConfig
import com.example.management.common.domain.FileDO
import com.example.management.common.domain.Tree
import com.example.management.common.domain.UserRoleDO
import com.example.management.common.service.FileService
import com.example.management.common.utils.*
import com.example.management.system.dao.DeptDao
import com.example.management.system.dao.UserDao
import com.example.management.system.dao.UserRoleDao
import com.example.management.system.domain.DeptDO
import com.example.management.system.domain.UserDO
import com.example.management.system.service.UserService
import com.example.management.system.vo.UserVO
import org.apache.commons.lang.ArrayUtils
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import org.springframework.web.multipart.MultipartFile

import javax.imageio.ImageIO
import java.io.ByteArrayOutputStream
import java.util.*

@Transactional
@Service
class UserServiceImpl : UserService {



    @Autowired
    internal var userMapper: UserDao? = null
    @Autowired
    internal var userRoleMapper: UserRoleDao? = null
    @Autowired
    internal var deptMapper: DeptDao? = null
    @Autowired
    private val sysFileService: FileService? = null
    @Autowired
    private val bootdoConfig: BootdoConfig? = null

    // 默认顶级菜单为０，根据数据库实际情况调整
    override fun getTree(): Tree<DeptDO> {
        val trees = ArrayList<Tree<DeptDO>>()
        val depts = deptMapper!!.list(HashMap<String, Any>(16))
        val pDepts = deptMapper!!.listParentDept()
        val uDepts = userMapper!!.listAllDept()
        val allDepts = ArrayUtils.addAll(pDepts, uDepts) as Array<Long>
        for (dept in depts) {
            if (!ArrayUtils.contains(allDepts, dept.deptId)) {
                continue
            }
            val tree = Tree<DeptDO>()
            tree.id = (dept.deptId.toString())
            tree.parentId = (dept.parentId.toString())
            tree.text =(dept.name)
            val state = HashMap<String, Any>(16)
            state["opened"] = true
            state["mType"] = "dept"
            tree.state = (state)
            trees.add(tree)
        }
        val users = userMapper!!.list(HashMap<String, Any>(16))
        for (user in users) {
            val tree = Tree<DeptDO>()
            tree.id = (user.userId.toString())
            tree.parentId= (user.deptId.toString())
            tree.text = (user.name)
            val state = HashMap<String, Any>(16)
            state["opened"] = true
            state["mType"] = "user"
            tree.state = (state)
            trees.add(tree)
        }
        return BuildTree.build(trees)!!
    }

    override operator fun get(id: Long?): UserDO {
        val roleIds = userRoleMapper!!.listRoleId(id)
        val user = userMapper!!.get(id)
        user.deptName = (deptMapper!!.get(user.deptId).name)
        user.roleIds = (roleIds)
        return user
    }

    override fun list(map: Map<String, Any>): List<UserDO> {
        return userMapper!!.list(map)
    }

    override fun count(map: Map<String, Any>): Int {
        return userMapper!!.count(map)
    }

    @Transactional
    override fun save(user: UserDO): Int {
        val count = userMapper!!.save(user)
        val userId = user.userId
        val roles = user.roleIds
        userRoleMapper!!.removeByUserId(userId)
        val list = ArrayList<UserRoleDO>()
        if (roles != null) {
            for (roleId in roles) {
                val ur = UserRoleDO()
                ur.userId = (userId)
                ur.roleId =(roleId)
                list.add(ur)
            }
        }
        if (list.size > 0) {
            userRoleMapper!!.batchSave(list)
        }
        return count
    }

    override fun update(user: UserDO): Int {
        val r = userMapper!!.update(user)
        val userId = user.userId
        val roles = user.roleIds
        userRoleMapper!!.removeByUserId(userId)
        val list = ArrayList<UserRoleDO>()
        if (roles != null) {
            for (roleId in roles) {
                val ur = UserRoleDO()
                ur.userId= (userId)
                ur.roleId = (roleId)
                list.add(ur)
            }
        }
        if (list.size > 0) {
            userRoleMapper!!.batchSave(list)
        }
        return r
    }

    override fun remove(userId: Long?): Int {
        userRoleMapper!!.removeByUserId(userId)
        return userMapper!!.remove(userId)
    }

    override fun exit(params: Map<String, Any>): Boolean {
        val exit: Boolean
        exit = userMapper!!.list(params).size > 0
        return exit
    }

    override fun listRoles(userId: Long?): Set<String>? {
        return null
    }

    @Throws(Exception::class)
    override fun resetPwd(userVO: UserVO, userDO: UserDO): Int {
        if (userVO.getUserDO().userId == userDO.userId) {
            if (MD5Utils.encrypt(userDO.username!!, userVO.getPwdOld()!!) == userDO.password) {
                userDO.password = (MD5Utils.encrypt(userDO.username!!, userVO.getPwdNew()!!))
                return userMapper!!.update(userDO)
            } else {
                throw Exception("输入的旧密码有误！")
            }
        } else {
            throw Exception("你修改的不是你登录的账号！")
        }
    }

    @Throws(Exception::class)
    override fun adminResetPwd(userVO: UserVO): Int {
        val userDO = get(userVO.getUserDO().userId)
        if ("admin" == userDO.username) {
            throw Exception("超级管理员的账号不允许直接重置！")
        }
        userDO.password = (MD5Utils.encrypt(userDO.username!!, userVO.getPwdNew()!!))
        return userMapper!!.update(userDO)


    }

    @Transactional
    override fun batchremove(userIds: Array<Long>): Int {
        val count = userMapper!!.batchRemove(userIds)
        userRoleMapper!!.batchRemoveByUserId(userIds)
        return count
    }

    override fun updatePersonal(userDO: UserDO): Int {
        return userMapper!!.update(userDO)
    }

    @Throws(Exception::class)
    override fun updatePersonalImg(file: MultipartFile, avatar_data: String, userId: Long?): Map<String, Any> {
        var fileName = file.originalFilename
        fileName = FileUtil.renameToUUID(fileName)
        val sysFile = FileDO(FileType.fileType(fileName), "/files/" + fileName!!, Date())
        //获取图片后缀
        val prefix = fileName!!.substring(fileName.lastIndexOf(".") + 1)
        val str = avatar_data.split(",".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
        //获取截取的x坐标
        val x = Math.floor(java.lang.Double.parseDouble(str[0].split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[1])).toInt()
        //获取截取的y坐标
        val y = Math.floor(java.lang.Double.parseDouble(str[1].split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[1])).toInt()
        //获取截取的高度
        val h = Math.floor(java.lang.Double.parseDouble(str[2].split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[1])).toInt()
        //获取截取的宽度
        val w = Math.floor(java.lang.Double.parseDouble(str[3].split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[1])).toInt()
        //获取旋转的角度
        val r = Integer.parseInt(str[4].split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[1].replace("}".toRegex(), ""))
        try {
            val cutImage = ImageUtils.cutImage(file, x, y, w, h, prefix)
            val rotateImage = ImageUtils.rotateImage(cutImage, r)
            val out = ByteArrayOutputStream()
            val flag = ImageIO.write(rotateImage, prefix, out)
            //转换后存入数据库
            val b = out.toByteArray()
            FileUtil.uploadFile(b, bootdoConfig!!.uploadPath, fileName)
        } catch (e: Exception) {
            throw Exception("图片裁剪错误！！")
        }

        val result = HashMap<String, Any>()
        if (sysFileService!!.save(sysFile) > 0) {
            val userDO = UserDO()
            userDO.userId= (userId)
            userDO.picId = (sysFile.id)
            if (userMapper!!.update(userDO) > 0) {
                result["url"] = sysFile.url!!
            }
        }
        return result
    }

    companion object {
        private val logger = LoggerFactory.getLogger(UserService::class.java!!)
    }

}
